from sqlalchemy import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy.sql import text
from sqlalchemy.orm import relationship, backref
import argparse
from config import Config
from argparse import ArgumentParser
import os.path
import logging
import logging.config
from netflow import pynfdump
from netflow import nfdata


def config_setting():
    """reading file paths from config file
    Args:
    none
    Returns:
    the path of log configuration file, database and source of nfcapd file
    Raises:
    Argument Error

    """
    parser = ArgumentParser()
    try:
        parser.add_argument("-c", dest="filename", required=True, help="config file")
        args = parser.parse_args()
        f = file(args.filename)
        cfg = Config(f)
        logfile = cfg.log
        dbpath = cfg.database
        ipadd = cfg.ip
        file_path = cfg.path
        file_source = cfg.source
        no_of_days = cfg.no_of_days
    except Exception as ex:
        make_log(logfile, 'exception in config file reading is %s' % ex)
    return dbpath, ipadd, file_path, file_source, logfile, no_of_days


def make_log(logfile, msg):
    """ logging
    Args:
    log_file: Path for logging configuration file
    msg: The message to be logged
    Raises:
    FileError: Path of log files not set properly 

    """
    logging.config.fileConfig(logfile)
    logger = logging.getLogger('nfuser')
    logger.info(msg)


def database_connectivity(dbpath, ipadd, file_path, file_source, logfile, no_of_days):
    """making nfdump entry into database
    Args:
    dbpath: path needed by SQLAlchemy to connect to the database
    ipadd: to log data of a particular ip address
    file_path: path to the directory containing live data
    file_source: exact directory under live
    logfile: path for logging configuration file
    Raises:database connectivity error

    """
    Base = declarative_base()
    #database session
    db = create_engine(dbpath, echo=False, echo_pool=True)
    #db.pool_recycle()
    Session = sessionmaker(bind=db)
    session = Session()
    ip = ipadd
    s=text(
    "DROP TRIGGER IF EXISTS update_rrd_key;"
    " CREATE TRIGGER  update_rrd_key BEFORE INSERT ON udp_entries"
	" FOR EACH ROW BEGIN"
  		" SET @rrd_key = 0;"
  		" SET @old_time = '2013-07-01 18:00:00';"
  		" SET @time_diff = 0;"
		" SET @sec_val = CONVERT(:day,UNSIGNED INTEGER);"
		" SET @sec_val = @sec_val*86400;"
  		" SELECT flow_time from udp_entries where rrd_key=1 into @old_time;"
  		" SELECT TIMESTAMPDIFF(SECOND, @old_time, NEW.flow_time) into @time_diff;"
  		" IF @time_diff > @sec_val THEN"
     			" SET NEW.rrd_key=1;  ELSE"
     			" SELECT rrd_key + 1"
       				" FROM statistic_rrd_key"
       				" INTO @rrd_key;"
     			" SET NEW.rrd_key = @rrd_key;"
  		" END IF;"
 		" UPDATE statistic_rrd_key SET rrd_key = NEW.rrd_key;"
  	" END;")
    session = Session()
    if no_of_days>1:
    	session.execute(s,{'day':no_of_days})
    d = pynfdump.Dumper(file_path,sources=[file_source])
    #d.set_where(start="2013-07-08 15:46")
    rec = d.search()
    for r in rec:
        l = r['last']
        si = str(r['srcip'])
        sp = str(r['srcport'])
        di = str(r['dstip'])
        dp = str(r['dstport'])
        b = r['bytes']
        packets = r['packets']
        flags = str(r['flags'])
        protocol = str(r['prot'])
        tos = str(r['tos'])
        try:
            session = Session()
            new_data = nfdata.Nfdata(l,si,sp,di,dp,b,packets,flags,protocol,tos)
            session.add(new_data)
            make_log(logfile,'database entry ')
            session.commit()
        except Exception as ex:
            make_log(logfile,'exception in database connectivity is %s' % ex)
	    #db.rollback()
    Base.metadata.create_all(db)
    session.close()
    


def main():
    try:
        dbpath, ipadd, file_path, file_source, logfile, no_of_days = config_setting()
    except Exception as ex:
        #make_log(logfile,'exception in main is %s' % ex)
        print ex;
    try:
        database_connectivity(dbpath, ipadd, file_path, file_source, logfile, no_of_days)
    except Exception as ex1:
        #make_log(logfile,'exception in main is %s' % ex)
        print ex1;

if  __name__ =='__main__':main()
